﻿namespace HZY.Framework.Core.Utils;

/// <summary>
/// 日期工具
/// </summary>
public static class DateTimeUtil
{
    /// <summary>
    /// DateTime
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value"></param>
    /// <returns></returns>
    public static DateTime ToDateTime<T>(this T value)
    {
        if (value == null) return DateTime.MinValue;

        return DateTime.TryParse(value.ToStr(), out var result) ? result : DateTime.MinValue;
    }

    /// <summary>
    /// DateTime?
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value"></param>
    /// <returns></returns>
    public static DateTime? ToDateTimeNull<T>(this T value)
    {
        if (value == null) return null;

        return DateTime.TryParse(value.ToStr(), out var result) ? (DateTime?)result : null;
    }

    /// <summary>
    /// 格式的 时间 字符串
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value"></param>
    /// <param name="formatStr"></param>
    /// <returns></returns>
    public static string ToDateTimeFormat<T>(this T value, string formatStr = "yyyy-MM-dd")
    {
        var datetime = value.ToDateTime();
        return datetime.ToShortDateString() == DateTime.MinValue.ToShortDateString()
            ? string.Empty
            : datetime.ToString(formatStr);
    }

    /// <summary>
    /// 将字符串日期 转化为 日期类型
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    public static DateTime ToDateTimeByString(this string value)
    {
        try
        {
            if (string.IsNullOrWhiteSpace(value))
            {
                return DateTime.MinValue;
            }

            if (value.Contains('-') || value.Contains('/'))
            {
                return DateTime.Parse(value);
            }

            int length = value.Length;
            return length switch
            {
                4 => DateTime.ParseExact(value, "yyyy", System.Globalization.CultureInfo.CurrentCulture),
                6 => DateTime.ParseExact(value, "yyyyMM", System.Globalization.CultureInfo.CurrentCulture),
                8 => DateTime.ParseExact(value, "yyyyMMdd", System.Globalization.CultureInfo.CurrentCulture),
                10 => DateTime.ParseExact(value, "yyyyMMddHH", System.Globalization.CultureInfo.CurrentCulture),
                12 => DateTime.ParseExact(value, "yyyyMMddHHmm", System.Globalization.CultureInfo.CurrentCulture),
                14 => DateTime.ParseExact(value, "yyyyMMddHHmmss", System.Globalization.CultureInfo.CurrentCulture),
                _ => DateTime.ParseExact(value, "yyyyMMddHHmmss", System.Globalization.CultureInfo.CurrentCulture),
            };
        }
        catch
        {
            return DateTime.MinValue;
        }
    }

    /// <summary>
    /// 判断字符串是否为时间戳
    /// <para>注意 : 默认 仅限于 2000年之后 到当前时间 的时间戳</para>
    /// </summary>
    /// <param name="timestampString"></param>
    /// <param name="startTime"></param>
    /// <param name="endTime"></param>
    /// <returns></returns>
    public static bool IsTimestampString(string timestampString, DateTime? startTime = null, DateTime? endTime = null)
    {
        if (string.IsNullOrWhiteSpace(timestampString)) return false;

        // 时间戳必须是正整数
        if (!Regex.IsMatch(timestampString, @"^[0-9]*$"))
        {
            return false;
        }

        if (!long.TryParse(timestampString, out var time)) return false;

        if (time < 1) return false;

        // 默认时间范围
        if (time > DateTimeOffset.MaxValue.ToUnixTimeSeconds())
        {
            return false;
        }

        if (time < DateTimeOffset.MinValue.ToUnixTimeSeconds())
        {
            return false;
        }

        if (startTime == null)
        {
            startTime = new DateTime(2000, 1, 1);
        }

        if (endTime == null)
        {
            endTime = DateTime.Now.AddDays(1);
        }

        // 将时间范围转为时间戳 秒级 然后判断 time时间戳是否在范围内
        if (startTime.HasValue && endTime.HasValue)
        {
            var start = startTime.Value.ToUnixTimeSeconds();
            var end = endTime.Value.ToUnixTimeSeconds();
            // 如果时间戳不在范围内
            if (time < start || time > end) return false;
        }

        var dateTime = ToLocalDateTimeString(time);

        var date = DateTimeUtil.ToDateTimeByString(dateTime);

        return date > startTime && date <= endTime;
    }

    /// <summary>
    /// 转时间戳
    /// </summary>
    /// <param name="dateTime"></param>
    /// <returns></returns>
    public static long ToUnixTimeSeconds(this DateTime dateTime)
    {
        // 将日期时间转换为时间戳（Unix时间戳）
        return ((DateTimeOffset)dateTime).ToUnixTimeSeconds();
    }

    /// <summary>
    /// 时间戳转换为 utc
    /// </summary>
    /// <param name="timeStamp"></param>
    /// <returns></returns>
    public static DateTime ToDateTimeUtc(this long? timeStamp)
    {
        if (timeStamp == null)
        {
            return DateTime.MinValue;
        }

        var dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds((long)timeStamp);
        return dateTimeOffset.UtcDateTime;
        //return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)
        //    .AddSeconds(timeStamp)
        //    .ToLocalTime();
    }

    /// <summary>
    /// 时间戳转换为 local 时间
    /// </summary>
    /// <param name="timeStamp"></param>
    /// <returns></returns>
    public static DateTime ToDateTimeLocal(this long? timeStamp)
    {
        if (timeStamp == null)
        {
            return DateTime.MinValue;
        }

        var dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds((long)timeStamp);
        return dateTimeOffset.LocalDateTime;
        //return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local)
        //    .AddSeconds(timeStamp)
        //    .ToLocalTime();
    }

    /// <summary>
    /// 时间戳(毫秒)转换为 utc
    /// </summary>
    /// <param name="timeStamp"></param>
    /// <returns></returns>
    public static DateTime ToUtcDateTimeMs(this long timeStamp)
    {
        var dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(timeStamp);
        return dateTimeOffset.UtcDateTime;
    }

    /// <summary>
    /// 时间戳(毫秒)转换为 local 时间
    /// </summary>
    /// <param name="timeStamp"></param>
    /// <returns></returns>
    public static DateTime ToLocalDateTimeMs(this long timeStamp)
    {
        var dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(timeStamp);
        return dateTimeOffset.LocalDateTime;
    }

    /// <summary>
    /// 时间戳转换为本地时间
    /// </summary>
    /// <param name="timeStamp"></param>
    /// <returns></returns>
    public static string ToLocalDateTimeString(this long timeStamp)
    {
        var time = ToDateTimeLocal(timeStamp);

        if (time == DateTime.MinValue)
        {
            return string.Empty;
        }

        return time.ToString("yyyy-MM-dd HH:mm:ss");
    }

    /// <summary>
    /// 判断字符串是否为有效的 日期类型
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public static bool IsDateTimeByString(string? input)
    {
        if (string.IsNullOrWhiteSpace(input))
        {
            return false;
        }

        // 正则验证是否纯正整数
        if (Regex.IsMatch(input, @"^[0-9]*$"))
        {
            return false;
        }

        if (double.TryParse(input, out var val) && val > 0)
        {
            return false;
        }

        if (!input.Contains('-') && !input.Contains('/'))
            return false;

        //if ( DateTime.TryParse(input, out DateTime date))
        var date = DateTimeUtil.ToDateTimeByString(input);
        if (date > DateTime.MinValue && date < DateTime.MaxValue)
        {
            return true;
        }

        return false;
    }

    /// <summary>
    /// 转化 天 时 分 秒
    /// </summary>
    /// <param name="timeDifference"></param>
    /// <returns></returns>
    public static string ToDayHourMinutesSeconds(this TimeSpan timeDifference)
    {
        // 获取时间间隔的各个部分
        int days = timeDifference.Days;
        int hours = timeDifference.Hours;
        int minutes = timeDifference.Minutes;
        int seconds = timeDifference.Seconds;

        return $"{days}天{hours}小时{minutes}分钟{seconds}秒";
    }

    /// <summary>
    /// 时间戳转为C#格式时间
    /// </summary>
    /// <param name="timeStamp"></param>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public static DateTime ToTime<T>(this int timeStamp)
    {
        var dtStart = TimeZoneInfo.ConvertTime(new DateTime(1970, 1, 1), TimeZoneInfo.Local);
        var lTime = long.Parse(timeStamp + "0000000");
        var toNow = new TimeSpan(lTime);
        return dtStart.Add(toNow);
    }

    /// <summary>
    /// DateTime时间格式转换为Unix时间戳格式
    /// </summary>
    /// <param name="time"></param>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public static int ToTimeInt<T>(this DateTime time)
    {
        var startTime = TimeZoneInfo.ConvertTime(new DateTime(1970, 1, 1), TimeZoneInfo.Local);
        return (int)((time) - startTime).TotalSeconds;
    }

}
